package com.diaohw.platform.framework.db.generator;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.diaohw.platform.framework.db.obj.BaseModel;
import lombok.Builder;
import lombok.SneakyThrows;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.type.JdbcType;

import java.io.File;
import java.util.*;

@Builder
public class MybatisGenerator {
    /**
     * 基类
     */
    private Class<?> baseClass;

    /**
     * 作者
     */
    private String author;

    /**
     * 数据库URL
     */
    private String url;
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * sql driver
     */
    private String driverClassName;

    /**
     * 模式名称
     */
    private String schema;
    /**
     * 表名
     */
    @Builder.Default
    private List<String> tables = new ArrayList<>();


    @Builder.Default
    private Class<?> entitySupperClass = BaseModel.class;

    @SneakyThrows
    public void generate() {
        String packageName = baseClass.getPackage().getName();
        System.out.println(packageName);
        File parentFile = new File(Objects.requireNonNull(baseClass.getClassLoader().getResource("")).toURI()).getParentFile().getParentFile();
        File java = new File(parentFile, "src/main/java");
        File mapper = new File(parentFile, "src/main/resources/mapper");

        Map<OutputFile, String> outputFileStringMap = new HashMap<>();

        outputFileStringMap.put(OutputFile.xml, mapper.getAbsolutePath());

        DataSourceConfig.Builder dataSource = new DataSourceConfig.Builder(createDataSource());
        dataSource.schema(schema);
        dataSource.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
            if (metaInfo.getJdbcType() == JdbcType.TINYINT) {
                if (metaInfo.getLength() > 1) {
                    return DbColumnType.INTEGER;
                }
                return DbColumnType.BOOLEAN;
            }
            return typeRegistry.getColumnType(metaInfo);
        });

        FastAutoGenerator.create(dataSource)

                // 全局配置
                .globalConfig((scanner, builder) ->

                        builder.author(author)
                                .enableSpringdoc()
                                .dateType(DateType.TIME_PACK)
                                .disableOpenDir()
                                .outputDir(java.getAbsolutePath())
                )
                // 包配置
                .packageConfig((scanner, builder) ->
                        builder.parent(packageName)
                                .entity("obj.entity")
                                .service("service")
                                .serviceImpl("service.impl")
                                .mapper("mapper")
                                .controller("controller")
                                .pathInfo(outputFileStringMap)

                )

                // 策略配置
                .strategyConfig((scanner, builder) -> {
//                            if (StrUtil.isNotBlank(schema)) {
//                                builder.enableSchema();
//                            }
                            builder.addInclude(tables)
                                    .controllerBuilder()
                                    .template("/template/controller.java")
                                    .enableRestStyle()
                                    .formatFileName("%sController")
                                    .enableRestStyle()
                                    .enableHyphenStyle()
                                    .enableFileOverride()
                                    .build()

                                    .serviceBuilder()
                                    .serviceTemplate("/template/service.java")
                                    .serviceImplTemplate("/template/serviceImpl.java")
                                    .formatServiceFileName("%sService")
                                    .formatServiceImplFileName("%sImpl")
                                    .enableFileOverride()
                                    .build()

                                    .mapperBuilder()
                                    .enableFileOverride()
                                    .mapperTemplate("/template/mapper.java")
                                    .mapperXmlTemplate("/template/mapper.xml")
                                    .enableBaseResultMap()
                                    .enableBaseColumnList()
                                    .mapperAnnotation(Mapper.class)
                                    .superClass(BaseMapper.class)
                                    .formatMapperFileName("%sMapper")
                                    .formatXmlFileName("%sMapper")
                                    .build()

                                    .entityBuilder()
                                    .javaTemplate("/template/entity.java")
                                    .formatFileName("%sDO")
                                    .enableFileOverride()
                                    .enableLombok()
                                    .enableTableFieldAnnotation()
                                    .enableActiveRecord()
                                    .addIgnoreColumns("id", "created_time", "created_by", "updated_by", "updated_time")
                                    .enableChainModel()
                                    .enableRemoveIsPrefix()
                                    .build();
                        }

                )

                .injectionConfig((scanner, builder) -> {

                    builder.customFile(CustomerFileEngine.load());
                    builder.beforeOutputFile(((tableInfo, stringObjectMap) -> {
                        CustomerFileEngine.beforeCustomerProcess(tableInfo, stringObjectMap);
                        if (entitySupperClass != null) {
                            stringObjectMap.put("superEntityClass", entitySupperClass.getSimpleName());
                            tableInfo.getImportPackages().add(entitySupperClass.getName());
                        }
                    }));
                })
                // 使用Freemarker引擎模板，默认的是Velocity引擎模板
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();

        System.out.println("success....");
    }


    private DruidDataSource createDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setPassword(password);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setDriverClassName(driverClassName);
        return dataSource;
    }

    public static void main(String[] args) {
        MybatisGenerator generator = MybatisGenerator.builder()
                .url("jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8")
                .username("root")
                .password("123456")
                .author("D-Hw")
                .tables(List.of("account"))
                .baseClass(MybatisGenerator.class)
                .build();
        generator.generate();
    }

}
